/**
 * Created by dl on 2018/11/6.
 * Description axios封装
 */
import axios from "axios";
import qs from "qs";
import { Connect } from "./apiURL";
import { getToken } from "@/utils/token";
import { Message, Notification } from "element-ui";
import store from "@/store";
import Vue from "vue";
import apiData from "../mock/index";
// const apiData = {};

// axios全局配置
axios.defaults.timeout = 6000 * 5; // 超时时间
// 请求类型
const GET = "get";
const POST = "post";
const DELETE = "delete";
const HEAD = "head";
const OPTIONS = "options";
const PUT = "put";
const PATCH = "patch";
const IS_MOCK = true;
// 请求格式
const MANNER_JSON = "application/json;charset=UTF-8"; // json 类型
const MANNER_FORM_DATA = "application/x-www-form-urlencoded;charset=UTF-8"; // form-data 提交类型
const MANNER_XML = "text/xml;charset=UTF-8"; // xml 类型
// 展示错误信息弹窗标识
let showErrorFlag = true;

/**
 * 弹出错误信息
 * @param url 错误地址
 * @param data 错误请求参数
 * @param err 错误响应
 * @return {*}
 */
function showErrorInfo(url, data, err) {
  Notification.error({
    title: "接口报错信息: ",
    dangerouslyUseHTMLString: true,
    duration: 6000,
    message: `
    <div >
    <p style="margin-bottom: 40px">
      请求地址: 
      <br/>
      ${url}
    </p>
    <p style="margin-bottom: 40px">
      请求参数: 
      <br/>
      ${data}
    </p>
    <div style="margin-bottom: 40px">
      响应参数: 
      <br/>
      <div style="max-width: 600px; max-height: 600px; over-flow: auto;">
      ${err}
      </div>
    </div>
  </div>`,
  });
}

// http request 拦截
axios.interceptors.request.use(
  (config) => {
    if (config.method !== "get") {
      // 接口需要loading, 默认需要
      // Vue.prototype.$load.loading();
    }

    // 对token进行传递
    let token = getToken();
    // 不携带token
    let noToken = config.url.includes("/auth/login/refreshToken/");
    token && !noToken && (config.headers.Authorization = token);
    return config;
  },
  (error) => Promise.reject(error),
);

// 定义接口数组, 当接口出现登录过期时重新发请求
let apiArr = [];
// let obj = apiData
// http response 拦截
axios.interceptors.response.use(
  (response) => {
    if (IS_MOCK) {
      // Vue.prototype.$load.close();
      let res = apiData[response.config.url].data;
      return res;
    }
    // setTimeout(() => {
    //   Vue.prototype.$load.close();
    // }, 300);
    // obj[response.config.url] = {};
    // obj[response.config.url].method = response.config.method;
    // obj[response.config.url].data = response.data;
    // window.localStorage.setItem("api", JSON.stringify(obj));
    if (response.data.code === 1) {
      // 弹出错误信息
      // showErrorInfo(response.config.url, response.config.data, JSON.stringify(response.data));
      Message.error(response.data.msg || "操作失败");
    }
    if (response.data.code === 2) {
      // token过期, 调用接口重新刷新token, 保证在多次发请求的时候只会触发一次刷新token
      // store.dispatch("logout", { noCallInterface: true });
      if (apiArr.length === 0) {
        store
          .dispatch("refreshToken")
          .then((res) => {
            if (res.code === 0) {
              apiArr.map((item) => {
                item.headers.Authorization = getToken();
                // 重新发请求
                axios(item);
              });
            } else {
              // 执行logout操作
              store.dispatch("logout");
            }
            apiArr = [];
          })
          .catch((err) => {
            // 执行logout操作
            store.dispatch("logout");
            apiArr = [];
          });
      }
      // 存放token过期前发请求的配置, 但是里面的授权信息是过期的
      apiArr.push(response.config);
    }

    return response.data;
  },
  (err) => {
    if (IS_MOCK) {
      // Vue.prototype.$load.close();
      let res = apiData[err.response.config.url].data;
      return res;
    }

    // 弹出错误信息
    // showErrorInfo(err.response.config.url, err.response.config.data, err);

    // setTimeout(() => {
    //   Vue.prototype.$load.close();
    // }, 300);

    if (err.response.data.code === 1) {
      return Message.error(err.response.data.msg || "操作失败");
    }

    if (err && err.response) {
      switch (err.response.status) {
        case 400:
          err.message = "错误请求";
          break;
        case 401:
          // store.dispatch("logout").then(() => {
          //   // 跳转首页
          //   Message.error("未授权, 请重新登录");
          // });
          err.message = "未授权，请重新登录";
          break;
        case 403:
          err.message = "拒绝访问";
          break;
        case 404:
          err.message = "请求错误,未找到该资源";
          break;
        case 405:
          err.message = "请求方法未允许";
          break;
        case 408:
          err.message = "请求超时";
          break;
        case 500:
          err.message = "服务器端出错";
          break;
        case 501:
          err.message = "网络未实现";
          break;
        case 502:
          err.message = "网络错误";
          break;
        case 503:
          err.message = "服务不可用";
          break;
        case 504:
          err.message = "网络超时";
          break;
        case 505:
          err.message = "http版本不支持该请求";
          break;
        default:
          err.message = `连接错误${err.response.status}`;
      }
    } else {
      err.message = "连接到服务器失败";
    }

    if (showErrorFlag) {
      showErrorFlag = false;
      Message.error({
        message: err.message || "服务器错误",
        // 弹窗消失后触发回调
        onClose() {
          showErrorFlag = true;
        },
      });
    }

    // return Promise.reject({ msg: err.message });
  },
);

/**
 * 请求封装
 * @param method 请求类型：post get delete put patch options head
 * @param url 请求地址
 * @param data 请求主体
 * @param params url参数
 * @param baseURL 地址
 * @param manner 请求方式：json form-data xml
 * @param isExport 导出true
 */

const request = (method, url, data, params, baseURL, manner, isExport = false) => {
  let com_base_url = Connect.baseURL;
  baseURL = baseURL ? baseURL : com_base_url;
  let config = {
    url: IS_MOCK && process.env.NODE_ENV === "development" ? url : baseURL + url,
    method,
    responseType: isExport ? "blob" : "",
    headers: {
      "Content-Type": manner ? manner : MANNER_JSON,
    },
    data: method === MANNER_FORM_DATA ? qs.stringify(data) : data,
    params,
  };
  return axios(config);
};

export { request, GET, POST, PUT, PATCH, OPTIONS, DELETE, HEAD, MANNER_JSON, MANNER_FORM_DATA, MANNER_XML };
